// scaup - Scala up!
// (c) 2008-2009, Normen Müller, normen.mueller@gmail.com  
// $Id: DOT.scala 38 2009-11-10 14:32:44Z normen.mueller $
package scaup.parsing.dot

import java.io.File
import java.text.MessageFormat.{format}

import scaup.Views._

/** 
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.2 */
case class DOTError(message: String) extends Exception(message)

/** This object provides a simple interface to the DOT parser class.
 * 
 *  Restricitons:
 *  o 'port', 'compass_p', and records are not yet supported
 *  o Nested fields are not recognized as such,
 *    e.g. "struct3 [shape=record,label="hello\nworld |{ b |{c|<here> d|e}| f}| g | h"]"
 *
 * @thanks to Ross Judson for his initial ideas regarding DOT parsing
 * @author <a href="mailto:normen.mueller@googlemail.com">Normen M&#xFC;ller</a>
 * @version 0.0.2 */
object DOT extends Parser {
  def apply(input: File): Graph =
    if(input == null || !(input exists))
      throw new DOTError(format("Physical DOT file may not be null (''{0}'').", input))
    else apply(input.content)
  
  def apply(input: String) =
    if(input == null)
      throw new DOTError("Physical DOT representation may not be null.")
    else parse(input)
  
  def parse(input: String) = phrase(graph)(new lexical.Scanner(input)) match {
    case Success(result, _) => result
    case n@_                => throw new DOTError(format("DOT parsing error in\n{0}\n\n", input) + n)

  }
}
